package com.zzl.bonds.ticket.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.bonds.ticket.constant.InvalidReasonEnum;
import com.zzl.bonds.ticket.constant.SourceTypeEnum;
import com.zzl.bonds.ticket.constant.StringConstant;
import com.zzl.bonds.ticket.constant.status.FrozenStatusEnum;
import com.zzl.bonds.ticket.constant.status.TicketCashingEnum;
import com.zzl.bonds.ticket.constant.status.TicketStatusEnum;
import com.zzl.bonds.ticket.constant.type.DataTypeEnum;
import com.zzl.bonds.ticket.constant.type.PaymentModeEnum;
import com.zzl.bonds.ticket.constant.type.TicketActionTypeEnum;
import com.zzl.bonds.ticket.constant.type.TicketTypeSourceEnum;
import com.zzl.bonds.ticket.dao.TicketDao;
import com.zzl.bonds.ticket.dto.*;
import com.zzl.bonds.ticket.dto.myticket.*;
import com.zzl.bonds.ticket.entity.*;
import com.zzl.bonds.ticket.feign.BaseDataFeign;
import com.zzl.bonds.ticket.service.*;
import com.zzl.bonds.ticket.service.common.MyTicketHandStatusService;
import com.zzl.bonds.ticket.service.common.TicketCommonService;
import com.zzl.bonds.ticket.untils.DateUtils;
import com.zzl.general.common.constant.Constant;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.requestparameter.StringIds;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.PageUtils;
import com.zzl.general.common.utils.Query;
import com.zzl.general.common.utils.UuidUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 我的票据
 *
 * @author sunpp
 * @date 2022-02-16 11:14:07
 */
@Slf4j
@Service("ticketService")
public class TicketServiceImpl extends ServiceImpl<TicketDao, TicketEntity> implements TicketService {

    @Autowired
    private TicketCommonService ticketCommonService;

    @Autowired
    private MyTicketHandStatusService myTicketHandStatusService;

    @Autowired
    private TicketTransferService ticketTransferService;

    @Autowired
    private TicketDataService ticketDataService;

    @Autowired
    private TicketOpenService ticketOpenService;

    @Autowired
    private TicketFinanceService ticketFinanceService;

    @Autowired
    private TicketOperateLogService ticketOperateLogService;

    @Autowired
    private BaseDataFeign baseDataFeign;

    /**
     * 冻结 或者解冻 凭证
     *
     * @param id   票的id
     * @param user 登录用户
     */
    @Override
    public String frozenTicket(String id, User user) {
        TicketEntity ticketEntity = this.getById(id);
        // 未冻结
        Integer frozenStatus = 0;
        if (frozenStatus.equals(ticketEntity.getFrozenState())) {
            frozenStatus = 1;
        }
        ticketEntity.setFrozenState(frozenStatus);
        ticketEntity.setUpdateTime(new Date());
        ticketEntity.setUpdaterId(user.getId());
        this.updateById(ticketEntity);
        return frozenStatus.equals(0) ? "冻结成功" : "解冻成功";
    }

    /**
     * 平台全部 票据
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryAllPage(Map<String, Object> params) throws SysException {
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<MyTicketPage> page = new Query<MyTicketPage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : pageField, Constant.ASC.equals(order));
        ticketCommonService.changeTenThousand2Number(params, "startAmount");
        ticketCommonService.changeTenThousand2Number(params, "endAmount");
        IPage<MyTicketPage> allPage = this.baseMapper.queryAllPage(page, params);
        List<MyTicketPage> pageRecords = allPage.getRecords();
        if (!CollectionUtils.isEmpty(pageRecords)) {
            myTicketHandStatusService.setMyTicketAllOperates(pageRecords);
            List<String> collect = pageRecords.stream().map(MyTicketPage::getTicketOriginId).distinct().collect(Collectors.toList());
            Collection<TicketEntity> ticketEntities = this.listByIds(collect);
            for (MyTicketPage pageRecord : pageRecords) {
                String surplusDays = ticketCommonService.calculateSurplusDays(pageRecord.getExpireTime(), pageRecord.getTicketStatus());
                pageRecord.setSurplusCashingDays(surplusDays);
                pageRecord.setTicketSourceStr(SourceTypeEnum.SELF_BUILD.getValue());
                pageRecord.setTicketStatusStr(TicketStatusEnum.getStatusName(pageRecord.getTicketStatus()));
                // 原始母单号
                ticketEntities.stream().filter(x -> x.getTicketOriginId().equals(pageRecord.getTicketOriginId())).findFirst()
                        .ifPresent(p -> pageRecord.setTicketOriginNo(p.getTicketNo()));
            }
        }
        return new PageUtils(page);
    }

    /**
     * 我持有的 票据
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params, User user) throws SysException {
        params.put("enterpriseId", user.getEnterpriseId());
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<MyTicketPage> page = new Query<MyTicketPage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : pageField, Constant.ASC.equals(order));
        ticketCommonService.changeTenThousand2Number(params, "startAmount");
        ticketCommonService.changeTenThousand2Number(params, "endAmount");
        IPage<MyTicketPage> holdPage = this.baseMapper.queryHoldPage(page, params);
        List<MyTicketPage> holdPageRecords = holdPage.getRecords();
        if (CollectionUtils.isEmpty(holdPageRecords)) {
            return new PageUtils(page);
        }
        List<TicketOpenEntity> ticketOpenEntities = new ArrayList<>(ticketOpenService.listByIds(
                holdPageRecords.stream().map(MyTicketPage::getTicketOpenId).distinct().collect(Collectors.toList())));
        Map<String, String> map = ticketOpenEntities.stream().collect(Collectors.toMap
                (TicketOpenEntity::getOpenEnterpriseId, TicketOpenEntity::getOpenSocialCreditCode, (item1, item2) -> item1));
        if (!CollectionUtils.isEmpty(holdPageRecords)) {
            myTicketHandStatusService.setMyTicketHoldOperates(holdPageRecords);
            for (MyTicketPage holdPageRecord : holdPageRecords) {
                String surplusDays = ticketCommonService.calculateSurplusDays(holdPageRecord.getExpireTime(), holdPageRecord.getTicketStatus());
                holdPageRecord.setSurplusCashingDays(surplusDays);
                holdPageRecord.setTicketSourceStr(SourceTypeEnum.SELF_BUILD.getValue());
                holdPageRecord.setTicketTypeSourceStr(TicketTypeSourceEnum.getFrontDisplay(holdPageRecord.getTicketTypeSource()));
                holdPageRecord.setPaymentModeInfo(PaymentModeEnum.getValue(holdPageRecord.getPaymentMode()));
                holdPageRecord.setOpenSocialCreditCode(map.get(holdPageRecord.getOpenEnterpriseId()));
            }
        }
        return new PageUtils(page);
    }

    /**
     * 转让中 票据
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryTransferIngPage(Map<String, Object> params, User user) throws SysException {
        params.put("enterpriseId", user.getEnterpriseId());
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<MyTicketPage> page = new Query<MyTicketPage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? "t.create_time" : "t." + pageField, Constant.ASC.equals(order));
        ticketCommonService.changeTenThousand2Number(params, "startAmount");
        ticketCommonService.changeTenThousand2Number(params, "endAmount");
        IPage<MyTicketPage> transferPage = this.baseMapper.queryTransferIngPage(page, params);
        List<MyTicketPage> transferRecords = transferPage.getRecords();
        if (!CollectionUtils.isEmpty(transferRecords)) {
            myTicketHandStatusService.setMyTicketTransferIngOperates(transferRecords);
            for (MyTicketPage transferRecord : transferRecords) {
                transferRecord.setTicketStatusStr(TicketStatusEnum.getStatusName(transferRecord.getTicketStatus()));
                transferRecord.setTicketSourceStr(SourceTypeEnum.SELF_BUILD.getValue());
            }
        }
        return new PageUtils(page);
    }

    private List<TicketransferEntity> getTransferTickets(List<String> transferIds) throws SysException {
        if (CollectionUtils.isEmpty(transferIds)) {
            return new ArrayList<>();
        }
        List<TicketransferEntity> entities = new ArrayList<>(ticketTransferService.listByIds(transferIds));
        if (CollectionUtils.isEmpty(entities)) {
            throw new SysException("在转让申请中未找到申请数据");
        }
        if (entities.size() != transferIds.size()) {
            throw new SysException("我的凭证存在部分凭证没有转让申请记录");
        }
        return entities;
    }

    /**
     * 融资中 票据
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryFinanceIngPage(Map<String, Object> params, User user) throws SysException {
        params.put("enterpriseId", user.getEnterpriseId());
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<MyTicketFinancePage> page = new Query<MyTicketFinancePage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : "f." + pageField, Constant.ASC.equals(order));
        ticketCommonService.changeTenThousand2Number(params, "startAmount");
        ticketCommonService.changeTenThousand2Number(params, "endAmount");
        IPage<MyTicketFinancePage> financePage = this.baseMapper.queryFinanceIngPage(page, params);
        List<MyTicketFinancePage> pageRecords = financePage.getRecords();
        if (!CollectionUtils.isEmpty(pageRecords)) {
            myTicketHandStatusService.setMyTicketFinanceIngOperates(pageRecords);
        }
        return new PageUtils(page);
    }

    /**
     * 失效的 票据
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryInvalidIngPage(Map<String, Object> params, User user) throws SysException {
        params.put("enterpriseId", user.getEnterpriseId());
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<MyTicketInvalidPage> page = new Query<MyTicketInvalidPage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : pageField, Constant.ASC.equals(order));
        ticketCommonService.changeTenThousand2Number(params, "startAmount");
        ticketCommonService.changeTenThousand2Number(params, "endAmount");
        IPage<MyTicketInvalidPage> holdPage = this.baseMapper.queryInvalidPage(page, params);
        List<MyTicketInvalidPage> pageRecords = holdPage.getRecords();
        if (!CollectionUtils.isEmpty(pageRecords)) {
            myTicketHandStatusService.setMyTicketInvalidIngOperates(pageRecords);
            pageRecords.forEach(e -> {
                e.setInvalidReason(InvalidReasonEnum.getStatusName(e.getInvalidReason()));
            });
        }
        return new PageUtils(page);
    }

    /**
     * 我的票据--凭证信息
     *
     * @param id id
     * @return
     * @throws SysException 业务异常
     */
    @Override
    public MyTicketDetail getMyTicketDetail(String id) throws SysException {
        TicketEntity ticketEntity = this.getById(id);
        if (ObjectUtils.isEmpty(ticketEntity)) {
            throw new SysException("未找到当前票据");
        }
        MyTicketDetail ticketDetail = new MyTicketDetail();
        BeanUtils.copyProperties(ticketEntity, ticketDetail);
        // set 其他信息
        ticketDetail.setTicketStatusStr(TicketStatusEnum.getStatusName(ticketEntity.getTicketStatus()));
        String surplusDays = ticketCommonService.calculateSurplusDays(ticketEntity.getCashTime(), ticketEntity.getTicketStatus());
        //设置统一信用代码
        this.setCreditCode(ticketDetail);
        ticketDetail.setSurplusCashingDays(surplusDays);
        ticketDetail.setTicketTypeSourceStr(TicketTypeSourceEnum.getValue(ticketEntity.getTicketTypeSource()));
        ticketDetail.setPaymentModeInfo(PaymentModeEnum.getValue(ticketDetail.getPaymentMode()));
        TicketransferEntity ticketransferEntity = ticketTransferService.getById(ticketEntity.getParentBusinessId());

        if (!ObjectUtils.isEmpty(ticketransferEntity)) {
            // 转单时间
            ticketDetail.setTransferTime(ticketransferEntity.getCreateTime());
        }

        ticketDetail.setBusinessType(TicketTypeSourceEnum.getValue(ticketEntity.getTicketTypeSource()));
        if (TicketTypeSourceEnum.COUNTER_PARTY_LIST.contains(ticketEntity.getTicketTypeSource())) {
            String party = ticketEntity.getEnterpriseName() + "/" + ticketEntity.getInstinctyName() + "/" + ticketEntity.getParentEnterpriseName();
            ticketDetail.setCounterParty(party);
        }
        // 业务发生时间
        ticketDetail.setBusinessCreateTime(ticketEntity.getCreateTime());
        // 文件信息
        List<TicketDataEntity> dataList = ticketDataService.getByTicketId(ticketEntity.getParentBusinessId(), TicketActionTypeEnum.TICKET_TYPE_TICKET.getCode());
        if (!CollectionUtils.isEmpty(dataList)) {
            List<TicketDataEntity> ticketList = dataList.stream().filter(x -> x.getDataType().equals(DataTypeEnum.TICKET.getCode())).collect(Collectors.toList());
            ticketDetail.setProofList(ticketList);
            List<TicketDataEntity> invoiceList = dataList.stream().filter(x -> x.getDataType().equals(DataTypeEnum.INVOICE.getCode())).collect(Collectors.toList());
            ticketDetail.setInvoiceList(invoiceList);
        }
        return ticketDetail;
    }

    public void setCreditCode(MyTicketDetail ticketDetail) {
        Map<String, String> socialCreditCodeMap = baseDataFeign.getSocialCreditCode(new StringIds(
                Arrays.asList(ticketDetail.getEnterpriseId(), ticketDetail.getOpenEnterpriseId(), ticketDetail.getTransferEnterpriseId())));
        ticketDetail.setReceiveCreditCode(socialCreditCodeMap.get(ticketDetail.getEnterpriseId()));
        ticketDetail.setOpenCreditCode(socialCreditCodeMap.get(ticketDetail.getOpenEnterpriseId()));
        ticketDetail.setTransferCreditCode(socialCreditCodeMap.get(ticketDetail.getTransferCreditCode()));
    }


    /**
     * 平台 我的凭证--详情
     *
     * @param id 票id
     * @return
     * @throws SysException 业务异常
     */
    @Override
    public MyTicketDetail getPltMyTicketDetail(String id) throws SysException {
        MyTicketDetail myTicketDetail = this.getMyTicketDetail(id);
        // 设置母单信息
        TicketEntity origin = this.getById(myTicketDetail.getTicketOriginId());
        if (!ObjectUtils.isEmpty(origin)) {
            ParentTicketInfo parentTicketInfo = new ParentTicketInfo();
            MyTicketDetail originDetail = this.getMyTicketDetail(origin.getId());
            BeanUtils.copyProperties(originDetail, parentTicketInfo);
            myTicketDetail.setParentTicketInfo(parentTicketInfo);
        }

        return myTicketDetail;
    }

    /**
     * 设置业务发生时间
     *
     * @param ticketDetail 我的票据
     */
    private void setBusinessCreateTime(MyTicketDetail ticketDetail) {
        Integer ticketTypeSource = ticketDetail.getTicketTypeSource();
        if (TicketTypeSourceEnum.OPEN.getCode().equals(ticketTypeSource)) {
            ticketDetail.setBusinessCreateTime(ticketDetail.getCreateTime());
        } else if (TicketTypeSourceEnum.TRANSFER_FINANCE_KEEP.getCode().equals(ticketTypeSource)) {
            TicketFinanceEntity finance = ticketFinanceService.getById(ticketDetail.getParentBusinessId());
            if (!ObjectUtils.isEmpty(finance)) {
                ticketDetail.setBusinessCreateTime(finance.getCreateTime());
            }
        } else {
            // 转让的 开单信息
            TicketransferEntity transfer = ticketTransferService.getById(ticketDetail.getParentBusinessId());
            if (!ObjectUtils.isEmpty(transfer)) {
                ticketDetail.setBusinessCreateTime(transfer.getCreateTime());
                ticketDetail.setRemark(transfer.getReceiveRemark());
            }
        }
    }

    /**
     * 我的票据--业务信息
     *
     * @param id id
     * @return
     * @throws SysException 业务异常
     */
    @Override
    public MyTicketBusinessDetail getTicketBusinessDetail(String id) throws SysException {
        TicketEntity ticketEntity = this.getById(id);
        if (ObjectUtils.isEmpty(ticketEntity)) {
            throw new SysException("未找到当前票据");
        }
        MyTicketBusinessDetail businessDetail = new MyTicketBusinessDetail();
        BeanUtils.copyProperties(ticketEntity, businessDetail);
        businessDetail.setBusinessType("测试");
        // set 其他信息
        businessDetail.setReceivableAmount(ticketEntity.getTicketAllAmount());
        // 业务发生时间
        if (ticketEntity.getTicketTypeSource().equals(TicketTypeSourceEnum.OPEN.getCode())) {
            TicketOpenEntity openEntity = ticketOpenService.getById(ticketEntity.getParentId());
            if (ObjectUtils.isEmpty(openEntity)) {
                throw new SysException("未找到开单凭证信息");
            }
            businessDetail.setBusinessCreateTime(openEntity.getCreateTime());
        } else {
            TicketransferEntity ticketransferEntity = ticketTransferService.getById(ticketEntity.getParentId());
            if (ObjectUtils.isEmpty(ticketransferEntity)) {
                throw new SysException("未找到当前转让数据");
            }
            businessDetail.setBusinessCreateTime(ticketransferEntity.getCreateTime());
        }
        businessDetail.setBusinessStatus("测试状态");

        // 文件信息
        List<TicketDataEntity> dataList = ticketDataService.getByTicketId(ticketEntity.getParentId(), TicketActionTypeEnum.TICKET_TYPE_TICKET.getCode());
        if (!CollectionUtils.isEmpty(dataList)) {
            List<TicketDataEntity> ticketList = dataList.stream().filter(x -> x.getDataType().equals(DataTypeEnum.TICKET.getCode())).collect(Collectors.toList());
            businessDetail.setProofList(ticketList);
            List<TicketDataEntity> invoiceList = dataList.stream().filter(x -> x.getDataType().equals(DataTypeEnum.INVOICE.getCode())).collect(Collectors.toList());
            businessDetail.setInvoiceList(invoiceList);
        }
        return businessDetail;
    }


    /**
     * 开立保存 我的票据
     *
     * @param openEntity 开立实体
     * @param user       登录用户
     */
    @Override
    public String saveTicket(TicketOpenEntity openEntity, User user) {
        TicketEntity ticketEntity = new TicketEntity();
        ticketEntity.setId(UuidUtils.UUID());
        ticketEntity.setTicketNo(openEntity.getTicketNo());
        ticketEntity.setEnterpriseId(openEntity.getReceiveEnterpriseId());
        ticketEntity.setEnterpriseName(openEntity.getReceiveEnterpriseName());
        ticketEntity.setTicketAllAmount(openEntity.getTicketAmount());
        ticketEntity.setTicketAvailableAmount(openEntity.getTicketAmount());
        ticketEntity.setTicketSurplusAmount(openEntity.getTicketAmount());
        ticketEntity.setInvoiceTime(openEntity.getInvoiceTime());
        ticketEntity.setCashTime(openEntity.getCashTime());
        ticketEntity.setLimitDays(openEntity.getLimitDays());
        ticketEntity.setParentTicketNo(openEntity.getTicketNo());
        ticketEntity.setParentEnterpriseId(openEntity.getOpenEnterpriseId());
        ticketEntity.setParentEnterpriseName(openEntity.getOpenEnterpriseName());
        ticketEntity.setTicketStatus(TicketStatusEnum.NORMAL_HOLDING.getCode());
        ticketEntity.setContractNo(openEntity.getContractNo());
        ticketEntity.setTicketSource(SourceTypeEnum.SELF_BUILD.getCode());
        ticketEntity.setTicketTypeSource(TicketTypeSourceEnum.OPEN.getCode());
        ticketEntity.setParentId("0");
        ticketEntity.setParentTicketNo(openEntity.getTicketNo());
        ticketEntity.setParentBusinessId(openEntity.getId());
        ticketEntity.setCreatorId(user.getId());
        ticketEntity.setCreateTime(new Date());
        ticketEntity.setTicketOpenId(openEntity.getId());
        ticketEntity.setOrgId(user.getOrgId());
        ticketEntity.setInstinctyId(openEntity.getInstinctyId());
        ticketEntity.setInstinctyName(openEntity.getInstinctyName());
        ticketEntity.setChainAddress(openEntity.getChainAddress());
        ticketEntity.setOpenEnterpriseId(openEntity.getOpenEnterpriseId());
        ticketEntity.setOpenEnterpriseName(openEntity.getOpenEnterpriseName());
        ticketEntity.setOrgId(user.getOrgId());
        ticketEntity.setRemark(openEntity.getRemark());
        ticketEntity.setDeletedStatus(0);
        ticketEntity.setTicketOriginId(ticketEntity.getId());
        ticketEntity.setReceivableAmount(openEntity.getTicketAmount());
        this.save(ticketEntity);
        log.info("新增我的票据", JSON.toJSONString(ticketEntity));
        return ticketEntity.getId();
    }

    /**
     * 新增
     *
     * @param ticketAddDto 新增实体
     * @param user         当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void saveTicket(TicketAddDto ticketAddDto, User user) throws SysException {
        TicketEntity ticketEntity = new TicketEntity();
        BeanUtils.copyProperties(ticketAddDto, ticketEntity);
        // ticketEntity.setCreateUserId(user.getId());
        if (!this.save(ticketEntity)) {
            throw new SysException("A00001", "保存失败！");
        }
    }

    /**
     * 修改
     *
     * @param ticketUpdateDto 修改实体
     * @param user            当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void updateTicketById(TicketUpdateDto ticketUpdateDto, User user) throws SysException {
        TicketEntity ticketEntity = new TicketEntity();
        BeanUtils.copyProperties(ticketUpdateDto, ticketEntity);
        // ticketEntity.setUpdatedUserId(user.getId());
        if (!this.updateById(ticketEntity)) {
            throw new SysException("A00002", "修改失败！");
        }
    }

    @Override
    public TicketEntity getByTicketNo(String ticketNo) {
        QueryWrapper<TicketEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ticket_no", ticketNo);
        return getOne(queryWrapper);
    }

    @Override
    public PageUtils cashingPage(Map<String, Object> params, User user, String advancePaymentStatus) throws SysException {
        //排序字段：create_time
        String pageField = (String) params.get(Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(Constant.ORDER);
        IPage<CashTicketPage> page = new Query<CashTicketPage>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME_FILED : pageField, Constant.ASC.equals(order));
        IPage<CashTicketPage> holdPage = ticketOpenService.cashingPage(page, params);
        List<CashTicketPage> holdPageRecords = holdPage.getRecords();
        if (!CollectionUtils.isEmpty(holdPageRecords)) {
            List<String> openIds = holdPageRecords.stream().map(CashTicketPage::getId).collect(Collectors.toList());
            QueryWrapper<TicketEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ticket_type_source", TicketTypeSourceEnum.OPEN.getCode());
            queryWrapper.in("ticket_open_id", openIds);
            List<TicketEntity> entities = this.list(queryWrapper);
            Map<String, TicketEntity> maps = entities.stream().collect(Collectors.toMap(TicketEntity::getTicketOpenId,
                    Function.identity(), (key1, key2) -> key2));
            KeyValue keyValue = new KeyValue();
            if ("6".equals(advancePaymentStatus)) {
                keyValue.setValue("审核");
            } else {
                keyValue.setValue("详情");
            }
            for (CashTicketPage holdPageRecord : holdPageRecords) {
                String surplusDays = ticketCommonService.calculateSurplusDays(holdPageRecord.getCashTime(), holdPageRecord.getTicketStatus());
                holdPageRecord.setSurplusCashingDays(surplusDays);
                holdPageRecord.setTicketSourceStr(SourceTypeEnum.SELF_BUILD.getValue());
                TicketEntity ticketEntity = maps.get(holdPageRecord.getId());
                if (ticketEntity.getTicketStatus().equals(TicketStatusEnum.INVALID.getCode())) {
                    holdPageRecord.setTicketStatusStr(ticketEntity.getInvalidReason());
                } else {
                    holdPageRecord.setTicketStatus(ticketEntity.getTicketStatus());
                    holdPageRecord.setTicketStatusStr(TicketStatusEnum.getStatusName(holdPageRecord.getTicketStatus()));
                }
                if (Arrays.asList(TicketCashingEnum.OUTSTANDING.getCode(), TicketCashingEnum.WAITING_FOR_PAYMENT.getCode(),
                        TicketCashingEnum.OVERDUE_NON_PAYMENT.getCode()).contains(holdPageRecord.getCashStatus())) {
                    KeyValue cash = new KeyValue();
                    cash.setValue("兑付");
                    holdPageRecord.setOperateButton(Arrays.asList(keyValue, cash));
                } else {
                    holdPageRecord.setOperateButton(Collections.singletonList(keyValue));
                }
            }
        }
        return new PageUtils(page);
    }

    @Override
    public List<CashTicketPage> getCashList(String ticketOpenId, User user) throws SysException {
        if (user.getUserCategory() == 1) {
            throw new SysException("暂无权限");
        }
        List<CashTicketPage> result = new ArrayList<>();
        TicketOpenEntity ticketOpenEntity = ticketOpenService.getById(ticketOpenId);
        //未到期待兑付列表
        if (Arrays.asList(TicketCashingEnum.OUTSTANDING.getCode(),
                TicketCashingEnum.WAITING_FOR_PAYMENT.getCode(), TicketCashingEnum.OVERDUE_NON_PAYMENT.getCode()).contains(ticketOpenEntity.getCashStatus())) {
            List<CashTicketPage> entities = baseMapper.getPlatformCashListForStatus(ticketOpenId, Collections.singletonList(TicketStatusEnum.NORMAL_HOLDING.getCode()));
            List<String> ticketIds = entities.stream().filter(x -> x.getFrozenState().equals(FrozenStatusEnum.FROZEN_STATUS_YES.getCode())).map(CashTicketPage::getParentId).collect(Collectors.toList());
            List<CashTicketPage> list = null;
            if (!CollectionUtils.isEmpty(ticketIds)) {
                list = baseMapper.getByIds(ticketIds);
            }

            for (CashTicketPage entity : entities) {
                if (!FrozenStatusEnum.FROZEN_STATUS_YES.getCode().equals(entity.getFrozenState())) {
                    result.add(entity);
                }
            }
            if (list != null) {
                result.addAll(list);
            }
        } else if (TicketCashingEnum.APPROVE_CASHED.getCode().equals(ticketOpenEntity.getCashStatus())) {
            result = baseMapper.getPlatformCashList(ticketOpenId, Arrays.asList(TicketCashingEnum.APPROVE_CASHED.getCode()));
        } else if (Arrays.asList(TicketCashingEnum.CASHED.getCode(),
                TicketCashingEnum.OVERDUE_CASHED.getCode()).contains(ticketOpenEntity.getCashStatus())) {
            result = baseMapper.getPlatformCashList(ticketOpenId, Arrays.asList(TicketCashingEnum.CASHED.getCode(), TicketCashingEnum.OVERDUE_CASHED.getCode()));
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cashTicket(String ticketOpenId, User user) throws SysException {

        TicketOpenEntity ticketOpenEntity = ticketOpenService.getById(ticketOpenId);
        if (!Arrays.asList(TicketCashingEnum.OUTSTANDING.getCode(),
                TicketCashingEnum.WAITING_FOR_PAYMENT.getCode(),
                TicketCashingEnum.OVERDUE_NON_PAYMENT.getCode()).contains(ticketOpenEntity.getCashStatus())) {
            throw new SysException("该票未处于待兑付状态！");
        }
        ticketOpenEntity.setCashStatus(TicketCashingEnum.APPROVE_CASHED.getCode());
        ticketOpenEntity.setId(ticketOpenId);
        ticketOpenService.updateById(ticketOpenEntity);
        //处理票
        this.setTicketInvalid(ticketOpenEntity.getId(), user);
        //处理转让票状态
        this.setTransferInvalid(ticketOpenId, user);
        //处理融资数据
        this.setFinanceInvalid(ticketOpenId, user);
    }

    private void setFinanceInvalid(String ticketOpenId, User user) {
        QueryWrapper<TicketFinanceEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ticket_open_id", ticketOpenId);
        queryWrapper.in("ticket_status", Arrays.asList(
                TicketStatusEnum.FINANCE_PENDING_APPROVE.getCode(),
                TicketStatusEnum.FINANCE_PENDING_SIGN.getCode()
        ));
        List<TicketFinanceEntity> list = ticketFinanceService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            List<TicketOperateLogEntity> operateLogEntities = new ArrayList<>();

            ticketFinanceService.updateBatchById(list);
            //处理票据
            List<String> parentIds = new ArrayList<>();
            List<String> ticketRetentionIds = new ArrayList<>();
            List<String> ticketIds = new ArrayList<>();
            for (TicketFinanceEntity ticketFinanceEntity : list) {
                parentIds.add(ticketFinanceEntity.getParentTicketId());
                ticketRetentionIds.add(ticketFinanceEntity.getRetentionTicketId());
                ticketIds.add(ticketFinanceEntity.getTicketId());
            }
            Collection<TicketEntity> parent = this.listByIds(parentIds);
            Collection<TicketEntity> ticketRetention = this.listByIds(ticketRetentionIds);
            Collection<TicketEntity> ticket = this.listByIds(ticketIds);
            parent.forEach(e -> {
                e.setCashStatus(TicketCashingEnum.APPROVE_CASHED.getCode());
                e.setTicketStatus(TicketStatusEnum.WAITING_PAYMENT.getCode());
            });
            ticketRetention.forEach(e -> {
                e.setTicketStatus(TicketStatusEnum.INVALID.getCode());
                e.setInvalidReason(InvalidReasonEnum.WAITING_PAYMENT.getValue());
            });
            ticket.forEach(e -> {
                e.setTicketStatus(TicketStatusEnum.INVALID.getCode());
                e.setInvalidReason(InvalidReasonEnum.WAITING_PAYMENT.getValue());
            });
            parent.addAll(ticketRetention);
            parent.addAll(ticket);
            this.updateBatchById(parent);
        }

    }


    public void setTicketInvalid(String ticketOpenId, User user) {
        UpdateWrapper<TicketEntity> queryWrapper = new UpdateWrapper<>();
        queryWrapper.eq("ticket_open_id", ticketOpenId);
        queryWrapper.eq("frozen_state", FrozenStatusEnum.FROZEN_STATUS_NO.getCode());
        queryWrapper.eq("ticket_status", TicketStatusEnum.NORMAL_HOLDING.getCode());
        queryWrapper.set("ticket_status", TicketStatusEnum.WAITING_PAYMENT.getCode());
        queryWrapper.set("cash_status", 6);
        this.update(queryWrapper);
    }

    public void setTransferInvalid(String ticketOpenId, User user) {
    }

    /**
     * 预兑付 转让的回滚
     * 我的票据的 金额的回滚
     * 状态更改
     * todo 预兑付的 逻辑有部分修改
     *
     * @param days 时间毫秒数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void executeWaitingPayment(Integer days) {
        // 1. 获取 到达预兑付的 票据
        List<TicketEntity> advanceTransferTicket = getAdvanceTransferTicket(days);
        if (CollectionUtils.isEmpty(advanceTransferTicket)) {
            return;
        }
        // 2.1 票据可用金额 加上 ,转让中 和融资中的金额
        // 2.2 清零 转让中，融资中的金额
        // 2.3 更新 兑付状态未 等待兑付
        Date nowTime = new Date();
        for (TicketEntity ticketEntity : advanceTransferTicket) {
            Double transferFrozenAmount = ticketEntity.getTransferFrozenAmount();
            Double financeFrozenAmount = ticketEntity.getFinanceFrozenAmount();
            ticketEntity.setTicketAvailableAmount(ticketEntity.getTicketAvailableAmount() + transferFrozenAmount
                    + financeFrozenAmount);
            ticketEntity.setTransferFrozenAmount(0.0);
            ticketEntity.setFinanceFrozenAmount(0.0);
            ticketEntity.setCashStatus(TicketCashingEnum.WAITING_FOR_PAYMENT.getCode());
            ticketEntity.setUpdateTime(nowTime);
            ticketEntity.setAdvancePaymentStatus(1);
        }
        this.updateBatchById(advanceTransferTicket);
    }

    @Override
    public List<CashTicketPage> getPlatformCashList(String ticketId, User user) throws SysException {
        if (user.getUserCategory() == 1) {
            throw new SysException("暂无权限");
        }
        List<CashTicketPage> pages = baseMapper.getPlatformCashList(ticketId, Arrays.asList(TicketCashingEnum.APPROVE_CASHED.getCode()));
        for (CashTicketPage page : pages) {
            page.setTicketStatusStr(TicketStatusEnum.getStatusName(page.getTicketStatus()));
        }
        return pages;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvalCashing(CashTicketUpdateDto cashTicketUpdateDto, User user) {
        TicketOpenEntity ticketOpenEntity = ticketOpenService.getById(cashTicketUpdateDto.getId());
        ticketOpenEntity.setPaymentVouchers(String.join(",", cashTicketUpdateDto.getPaymentVouchers()));
        ticketOpenEntity.setCashStatus(TicketCashingEnum.CASHED.getCode());
        ticketOpenService.updateById(ticketOpenEntity);
        UpdateWrapper<TicketEntity> wrapper = new UpdateWrapper<>();
        wrapper.set("cash_status", TicketCashingEnum.CASHED.getCode());
        wrapper.set("ticket_status", TicketStatusEnum.PAID.getCode());
        wrapper.eq("ticket_open_id", cashTicketUpdateDto.getId());
        wrapper.eq("cash_status", TicketCashingEnum.APPROVE_CASHED.getCode());
        this.update(wrapper);
    }

    @Override
    public void approvalCashingReject(CashTicketUpdateDto cashTicketUpdateDto, User user) throws SysException {
        TicketOpenEntity ticketOpenEntity = ticketOpenService.getById(cashTicketUpdateDto.getId());
        ticketOpenEntity.setCashStatus(TicketCashingEnum.OUTSTANDING.getCode());
        UpdateWrapper<TicketEntity> wrapper = new UpdateWrapper<>();
        wrapper.set("cash_status", TicketCashingEnum.OUTSTANDING.getCode());
        wrapper.set("ticket_status", TicketStatusEnum.NORMAL_HOLDING.getCode());
        wrapper.eq("ticket_open_id", cashTicketUpdateDto.getId());
        wrapper.eq("cash_status", TicketCashingEnum.APPROVE_CASHED.getCode());
        this.update(wrapper);

        QueryWrapper<TicketransferEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ticket_open_id", ticketOpenEntity.getId());
        queryWrapper.in("ticket_status", Arrays.asList(TicketStatusEnum.TRANSFER_PENDING_REVIEW.getCode(),
                TicketStatusEnum.TRANSFER_PENDING_APPROVE.getCode(),
                TicketStatusEnum.TRANSFER_PENDING_SIGN.getCode()));
        List<TicketransferEntity> list = ticketTransferService.list(queryWrapper);

    }

    public void saveLogForFinance(String ticketOpenId, User user) {
        QueryWrapper<TicketFinanceEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ticket_open_id", ticketOpenId);
        queryWrapper.in("ticket_status", Arrays.asList(
                TicketStatusEnum.FINANCE_PENDING_APPROVE.getCode(),
                TicketStatusEnum.FINANCE_PENDING_SIGN.getCode()
        ));
        List<TicketFinanceEntity> list = ticketFinanceService.list(queryWrapper);
    }


    /**
     * 获取 我的票据 达到预兑付的 票据
     *
     * @param days 提前预兑付的日期
     * @return 达到预兑付的 票据
     */
    private List<TicketEntity> getAdvanceTransferTicket(Integer days) {
        // 截至兑付日期
        Date cashTime = DateUtils.dateAddDaysAll(days);
        if (ObjectUtils.isEmpty(cashTime)) {
            return new ArrayList<>();
        }
        QueryWrapper<TicketEntity> queryWrapper = new QueryWrapper<>();
        // 未兑付的状态 计算预兑付
        queryWrapper.lambda().eq(TicketEntity::getCashStatus, 1)
                // 兑付时间 范围
                .le(TicketEntity::getCashTime, cashTime);
        List<TicketEntity> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list;
    }

    /**
     * 根据开立申请id新增我的票据
     *
     * @param ticketOpenId 开立申请id
     * @param user         登录用户
     * @throws SysException 业务异常
     */
    @Override
    public String saveTicketByOpenId(String ticketOpenId, User user) throws SysException {
        TicketOpenEntity openEntity = ticketOpenService.getById(ticketOpenId);
        if (null == openEntity) {
            throw new SysException("开立申请不存在");
        }
        TicketEntity ticketEntity = new TicketEntity();
        String ticketId = UuidUtils.UUID();

        BeanUtils.copyProperties(openEntity, ticketEntity);
        ticketEntity.setCreatorId(user.getId());
        ticketEntity.setUpdaterId(user.getId());
        ticketEntity.setEnterpriseId(openEntity.getReceiveEnterpriseId());
        ticketEntity.setOrgId(user.getOrgId());
        ticketEntity.setFinanceAmount(0d);
        ticketEntity.setFinanceFrozenAmount(0d);
        ticketEntity.setTicketSurplusAmount(openEntity.getTicketAmount());
        ticketEntity.setTicketAllAmount(openEntity.getTicketAmount());
        ticketEntity.setTransferAmount(0d);
        ticketEntity.setTransferFrozenAmount(0d);
        ticketEntity.setOrgId(user.getOrgId());
        ticketEntity.setTicketAvailableAmount(openEntity.getTicketAmount());
        ticketEntity.setTicketOpenId(openEntity.getId());
        ticketEntity.setTicketTypeSource(TicketTypeSourceEnum.OPEN.getCode());
        ticketEntity.setCashStatus(TicketCashingEnum.OUTSTANDING.getCode());
        ticketEntity.setReceiptTime(new Date());
        ticketEntity.setId(ticketId);
        ticketEntity.setTicketStatus(TicketStatusEnum.NORMAL_HOLDING.getCode());
        ticketEntity.setContractNo(openEntity.getContractNo());
        ticketEntity.setTicketSource(1);
        ticketEntity.setParentEnterpriseId(openEntity.getOpenEnterpriseId());
        ticketEntity.setParentEnterpriseName(openEntity.getOpenEnterpriseName());
        ticketEntity.setParentBusinessId(openEntity.getId());
        ticketEntity.setFrozenState(0);
        ticketEntity.setOpenSocialCreditCode(openEntity.getOpenSocialCreditCode());
        ticketEntity.setExpireTime(openEntity.getExpireTime());
        ticketEntity.setEnterpriseName(openEntity.getReceiveEnterpriseName());
        ticketEntity.setEnterpriseId(openEntity.getReceiveEnterpriseId());
        if (!this.save(ticketEntity)) {
            throw new SysException("保存失败");
        }
        return ticketId;
    }

    @Override
    public SurveyInfo survey(User user) throws SysException {
        SurveyInfo surveyInfo = baseMapper.survey(user.getEnterpriseId());

        return null;
    }


}